package com.example.easytts.service

import com.example.easytts.model.VideoTask
import com.example.easytts.repository.VideoTaskRepository
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
import org.json.JSONObject
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Value
import org.springframework.scheduling.annotation.Async
import org.springframework.stereotype.Service
import org.springframework.web.reactive.function.client.WebClient
import org.springframework.http.MediaType
import org.springframework.web.multipart.MultipartFile
import java.io.File
import java.time.LocalDateTime
import java.util.*

@Service
class VideoGenerationService(
    private val videoTaskRepository: VideoTaskRepository,
    private val applicationContext: org.springframework.context.ApplicationContext
) {
    @Value("\${video.upload.dir:videos}")
    private lateinit var videoUploadDir: String
    
    private val logger = LoggerFactory.getLogger(VideoGenerationService::class.java)
    
    private val webClient = WebClient.builder()
        //.baseUrl("http://127.0.0.1:5001") // 本地视频生成服务地址
        .baseUrl("http://172.17.0.4:5001")
        .defaultHeader("User-Agent", "easytts")
        .build()

    private val objectMapper = jacksonObjectMapper()
    
    /**
     * 处理视频上传并解析字幕（同步处理）
     */
    fun processVideoUpload(file: MultipartFile, userId: Long?): Map<String, Any> {
        // 1. 保存上传的视频文件
        val videoDir = File(System.getProperty("user.dir"), videoUploadDir)
        if (!videoDir.exists()) videoDir.mkdirs()
        
        val ext = file.originalFilename?.substringAfterLast('.', "mp4")?.lowercase() ?: "mp4"
        val filename = UUID.randomUUID().toString() + "." + ext
        val videoFile = File(videoDir, filename)
        
        file.transferTo(videoFile)
        logger.info("视频文件已保存: ${videoFile.absolutePath}")
        
        // 3. 同步处理字幕解析
        try {
            // 直接调用字幕解析方法，不再使用异步
            return parseSubtitle(videoFile.absolutePath, filename)
        } catch (e: Exception) {
            logger.error("字幕解析任务失败:", e)
            throw e // 向上抛出异常，让控制器处理
        }
    }
    
    /**
     * 同步处理字幕解析
     */
    fun parseSubtitle(videoPath: String, filename: String): Map<String, Any> {
        try {
            // 创建一个MultipartBodyBuilder来构建multipart请求
            val bodyBuilder = org.springframework.web.reactive.function.BodyInserters.fromMultipartData(
                org.springframework.util.LinkedMultiValueMap<String, Any>().apply {
                    // 添加视频文件
                    add("file", org.springframework.core.io.FileSystemResource(videoPath))
                    // 添加其他参数
                    add("filename", filename)
                }
            )
            
            // 调用字幕解析服务
            val response = webClient.post()
                .uri("/parse_subtitle")  // Python Flask通常使用简单路由
                .contentType(MediaType.MULTIPART_FORM_DATA)
                .body(bodyBuilder)
                .retrieve()
                .bodyToMono(String::class.java)
                .block() ?: throw RuntimeException("字幕解析服务无响应")
    
    
            // 解析响应
            val responseJSONObject = JSONObject(response)
    
            // 检查响应是否成功
            val success = responseJSONObject["success"] as? Boolean ?: false
            println("success:" + success)
            if (!success) {
                throw RuntimeException("字幕解析失败: ${responseJSONObject["message"]}")
            }
            // 获取字幕内容
            val content = responseJSONObject.optJSONObject("data")
                ?: throw RuntimeException("响应中缺少字幕内容")
    
            println("content:" + content)
            
            // 字幕解析成功后删除本地视频文件
            try {
                val videoFile = File(videoPath)
                if (videoFile.exists()) {
                    val deleted = videoFile.delete()
                    if (deleted) {
                        logger.info("本地视频文件已删除: $videoPath")
                    } else {
                        logger.warn("删除本地视频文件失败: $videoPath")
                    }
                }
            } catch (deleteException: Exception) {
                logger.error("删除本地视频文件时发生异常: $videoPath", deleteException)
                // 不抛出异常，因为字幕解析已经成功，文件删除失败不应该影响主流程
            }
            
            // 按照用户要求，直接返回处理结果作为data字段
            // 构建与Python服务返回格式一致的响应
            return mapOf(
                "success" to true,
                "message" to "视频字幕解析成功",
                "data" to content.toString()
            )
            
        } catch (e: Exception) {
            // 如果字幕解析失败，也尝试删除本地视频文件
            try {
                val videoFile = File(videoPath)
                if (videoFile.exists()) {
                    val deleted = videoFile.delete()
                    if (deleted) {
                        logger.info("字幕解析失败，已删除本地视频文件: $videoPath")
                    } else {
                        logger.warn("字幕解析失败，删除本地视频文件也失败: $videoPath")
                    }
                }
            } catch (deleteException: Exception) {
                logger.error("删除本地视频文件时发生异常: $videoPath", deleteException)
            }
            
            logger.error("字幕解析任务失败: ", e)
            throw e // 向上抛出异常，让控制器处理
        }
    }
    
    /**
     * 创建视频生成任务
     */
    fun createVideoTask(requestData: String, userId: Long? = null): String {
        val taskId = UUID.randomUUID().toString()
        
        val videoTask = VideoTask(
            taskId = taskId,
            requestData = requestData,
            userId = userId
        )
        
        videoTaskRepository.save(videoTask)
        logger.info("创建视频生成任务: $taskId")
        
        // 使用ApplicationContext来调用异步方法，避免自调用问题
        try {
            val self = applicationContext.getBean(VideoGenerationService::class.java)
            self.processVideoTaskAsync(taskId)
        } catch (e: Exception) {
            logger.error("启动异步任务失败: $taskId", e)
            // 即使异步启动失败，也要返回taskId
        }
        
        return taskId
    }

    /**
     * 根据任务ID查询任务状态
     */
    fun getTaskStatus(taskId: String): VideoTask? {
        return videoTaskRepository.findByTaskId(taskId)
    }

    /**
     * 获取用户的任务列表
     */
    fun getUserTasks(userId: Long): List<VideoTask> {
        return videoTaskRepository.findByUserIdOrderByCreatedAtDesc(userId)
    }

    /**
     * 删除任务
     */
    fun deleteTask(taskId: String): Boolean {
        return try {
            val task = videoTaskRepository.findByTaskId(taskId)
            if (task != null) {
                videoTaskRepository.delete(task)
                logger.info("删除视频任务: $taskId")
                true
            } else {
                logger.warn("尝试删除不存在的任务: $taskId")
                false
            }
        } catch (e: Exception) {
            logger.error("删除任务失败: $taskId", e)
            false
        }
    }

    /**
     * 异步处理视频生成任务
     */
    @Async("videoTaskExecutor")
    fun processVideoTaskAsync(taskId: String) {
        try {
            val task = videoTaskRepository.findByTaskId(taskId)
            if (task == null) {
                logger.error("任务不存在: $taskId")
                return
            }

            // 更新任务状态为处理中
            updateTaskStatus(taskId, "PROCESSING")

            // 解析请求数据
            val requestMap = objectMapper.readValue<Map<String, Any>>(task.requestData)
            
            // 调用本地视频生成服务
            val response = webClient.post()
                .uri("/api/video/generate")
                .contentType(MediaType.APPLICATION_JSON)
                .bodyValue(requestMap)
                .retrieve()
                .bodyToMono(String::class.java)
                .block() ?: throw RuntimeException("视频生成服务无响应")

            // 解析响应
            val responseMap = objectMapper.readValue<Map<String, Any>>(response)
            
            // 检查响应是否成功
            val success = responseMap["success"] as? Boolean ?: false
            if (!success) {
                throw RuntimeException("视频生成服务返回失败: ${responseMap["message"]}")
            }
            
            // 获取视频URL，支持多种字段名
            val resultUrl = responseMap["cos_url"] as? String
                ?: responseMap["video_url"] as? String
                ?: throw RuntimeException("响应中缺少视频URL字段")

            // 更新任务状态为完成
            updateTaskCompleted(taskId, resultUrl)
            
            logger.info("视频生成任务完成: $taskId, 结果URL: $resultUrl")

        } catch (e: Exception) {
            logger.error("视频生成任务失败: $taskId", e)
            updateTaskFailed(taskId, e.message ?: "未知错误")
        }
    }

    /**
     * 更新任务状态
     */
    private fun updateTaskStatus(taskId: String, status: String) {
        val task = videoTaskRepository.findByTaskId(taskId)
        task?.let {
            val updatedTask = it.copy(
                status = status,
                updatedAt = LocalDateTime.now()
            )
            videoTaskRepository.save(updatedTask)
        }
    }

    /**
     * 更新任务为完成状态
     */
    private fun updateTaskCompleted(taskId: String, resultUrl: String) {
        val task = videoTaskRepository.findByTaskId(taskId)
        task?.let {
            val updatedTask = it.copy(
                status = "COMPLETED",
                resultUrl = resultUrl,
                updatedAt = LocalDateTime.now()
            )
            videoTaskRepository.save(updatedTask)
        }
    }

    /**
     * 更新任务为失败状态
     */
    private fun updateTaskFailed(taskId: String, errorMessage: String) {
        val task = videoTaskRepository.findByTaskId(taskId)
        task?.let {
            val updatedTask = it.copy(
                status = "FAILED",
                errorMessage = errorMessage,
                updatedAt = LocalDateTime.now()
            )
            videoTaskRepository.save(updatedTask)
        }
    }
}
